/**
 * 测量工具类
 * 支持距离测量和面积测量
 */

import { Map as OlMap } from 'ol';
import { Draw, Modify, Snap } from 'ol/interaction';
import { Vector as VectorLayer } from 'ol/layer';
import { Vector as VectorSource } from 'ol/source';
import { Feature } from 'ol';
import { LineString, Polygon, Geometry } from 'ol/geom';
import { getLength, getArea } from 'ol/sphere';
import { Style, Stroke, Fill, Circle, Text } from 'ol/style';
import { Point } from 'ol/geom';
import { Coordinate } from '../types';
import { DataUtil } from '../utils/data';
import { EventEmitter } from '../utils/event';

/**
 * 测量类型
 */
export enum MeasureType {
  /** 距离测量 */
  DISTANCE = 'distance',
  /** 面积测量 */
  AREA = 'area'
}

/**
 * 测量工具配置
 */
export interface MeasureOptions {
  /** 测量类型 */
  type?: MeasureType;
  /** 线条样式 */
  lineStyle?: any;
  /** 填充样式 */
  fillStyle?: any;
  /** 标签样式 */
  labelStyle?: any;
  /** 是否显示标签 */
  showLabel?: boolean;
  /** 单位 */
  unit?: 'metric' | 'imperial';
}

/**
 * 测量结果
 */
export interface MeasureResult {
  /** 测量值 */
  value: number;
  /** 格式化后的文本 */
  text: string;
  /** 单位 */
  unit: string;
}

/**
 * 测量工具类
 */
export class Measure extends EventEmitter {
  /** 地图实例 */
  private map: OlMap | null = null;
  /** 测量类型 */
  private measureType: MeasureType;
  /** 绘制交互 */
  private drawInteraction: Draw | null = null;
  /** 修改交互 */
  private modifyInteraction: Modify | null = null;
  /** 捕捉交互 */
  private snapInteraction: Snap | null = null;
  /** 矢量图层 */
  private layer: VectorLayer<VectorSource<Feature<Geometry>>> | null = null;
  /** 矢量数据源 */
  private source: VectorSource<Feature<Geometry>> | null = null;
  /** 配置选项 */
  private options: MeasureOptions;
  /** 当前测量要素 */
  private currentFeature: Feature<Geometry> | null = null;

  /**
   * 构造函数
   * @param options 配置选项
   */
  constructor(options: MeasureOptions = {}) {
    super();
    this.options = {
      type: MeasureType.DISTANCE,
      showLabel: true,
      unit: 'metric',
      ...options
    };
    this.measureType = this.options.type || MeasureType.DISTANCE;
    this.createLayer();
  }

  /**
   * 创建图层
   */
  private createLayer(): void {
    this.source = new VectorSource<Feature<Geometry>>();
    this.layer = new VectorLayer({
      source: this.source,
      style: (feature) => this.getStyle(feature as Feature<Geometry>)
    });
  }

  /**
   * 获取样式
   */
  private getStyle(feature: Feature<Geometry>): Style[] {
    const geometry = feature.getGeometry();
    if (!geometry) return [];

    const styles: Style[] = [];

    if (geometry instanceof LineString) {
      // 线条样式
      styles.push(new Style({
        stroke: new Stroke({
          color: '#3399CC',
          width: 2,
          lineDash: [5, 5]
        })
      }));

      // 点样式
      geometry.getCoordinates().forEach((coord) => {
        styles.push(new Style({
          image: new Circle({
            radius: 5,
            fill: new Fill({ color: '#3399CC' }),
            stroke: new Stroke({ color: '#fff', width: 2 })
          }),
          geometry: new Point(coord)
        }));
      });

      // 标签样式
      if (this.options.showLabel) {
        const measure = this.measureLineString(geometry);
        const midCoord = geometry.getCoordinateAt(0.5) || geometry.getCoordinates()[0];
        styles.push(new Style({
          text: new Text({
            text: measure.text,
            fill: new Fill({ color: '#000' }),
            stroke: new Stroke({ color: '#fff', width: 3 }),
            font: '12px sans-serif',
            offsetY: -15
          }),
          geometry: new Point(midCoord)
        }));
      }
    } else if (geometry instanceof Polygon) {
      // 填充样式
      styles.push(new Style({
        fill: new Fill({
          color: 'rgba(51, 153, 204, 0.3)'
        }),
        stroke: new Stroke({
          color: '#3399CC',
          width: 2,
          lineDash: [5, 5]
        })
      }));

      // 点样式
      const coordinates = geometry.getCoordinates()[0];
      coordinates.forEach((coord) => {
        styles.push(new Style({
          image: new Circle({
            radius: 5,
            fill: new Fill({ color: '#3399CC' }),
            stroke: new Stroke({ color: '#fff', width: 2 })
          }),
          geometry: new Point(coord)
        }));
      });

      // 标签样式
      if (this.options.showLabel) {
        const measure = this.measurePolygon(geometry);
        const extent = geometry.getExtent();
        const center: [number, number] = [
          (extent[0] + extent[2]) / 2,
          (extent[1] + extent[3]) / 2
        ];
        styles.push(new Style({
          text: new Text({
            text: measure.text,
            fill: new Fill({ color: '#000' }),
            stroke: new Stroke({ color: '#fff', width: 3 }),
            font: '12px sans-serif'
          }),
          geometry: new Point(center)
        }));
      }
    }

    return styles;
  }

  /**
   * 测量线
   */
  private measureLineString(geometry: LineString): MeasureResult {
    const length = getLength(geometry);
    return this.formatDistance(length);
  }

  /**
   * 测量面
   */
  private measurePolygon(geometry: Polygon): MeasureResult {
    const area = getArea(geometry);
    return this.formatArea(area);
  }

  /**
   * 格式化距离
   */
  private formatDistance(length: number): MeasureResult {
    const unit = this.options.unit || 'metric';
    let value: number;
    let unitText: string;

    if (unit === 'imperial') {
      // 英制单位
      if (length > 1609.34) {
        value = length / 1609.34;
        unitText = 'mi';
      } else {
        value = length / 0.3048;
        unitText = 'ft';
      }
    } else {
      // 公制单位
      if (length > 1000) {
        value = length / 1000;
        unitText = 'km';
      } else {
        value = length;
        unitText = 'm';
      }
    }

    return {
      value,
      text: `${value.toFixed(2)} ${unitText}`,
      unit: unitText
    };
  }

  /**
   * 格式化面积
   */
  private formatArea(area: number): MeasureResult {
    const unit = this.options.unit || 'metric';
    let value: number;
    let unitText: string;

    if (unit === 'imperial') {
      // 英制单位
      value = area / 4046.86;
      unitText = 'acres';
    } else {
      // 公制单位
      if (area > 1000000) {
        value = area / 1000000;
        unitText = 'km²';
      } else {
        value = area;
        unitText = 'm²';
      }
    }

    return {
      value,
      text: `${value.toFixed(2)} ${unitText}`,
      unit: unitText
    };
  }

  /**
   * 初始化测量工具
   * @param map 地图实例
   */
  init(map: OlMap): void {
    if (this.map) {
      this.destroy();
    }

    this.map = map;
    
    // 添加图层
    if (this.layer) {
      map.addLayer(this.layer);
    }

    // 添加捕捉交互
    this.snapInteraction = new Snap({
      source: this.source!
    });
    map.addInteraction(this.snapInteraction);
  }

  /**
   * 开始测量
   * @param type 测量类型
   */
  start(type?: MeasureType): void {
    if (!this.map || !this.source) {
      throw new Error('Measure tool not initialized. Call init() first.');
    }

    // 停止当前测量
    this.stop();

    this.measureType = type || this.options.type || MeasureType.DISTANCE;
    const geometryType = this.measureType === MeasureType.AREA ? 'Polygon' : 'LineString';

    // 创建绘制交互
    this.drawInteraction = new Draw({
      source: this.source,
      type: geometryType as any,
      style: (feature) => this.getStyle(feature as Feature<Geometry>)
    });

    // 监听绘制事件
    this.drawInteraction.on('drawend', (event: any) => {
      const feature = event.feature;
      this.currentFeature = feature;
      
      const geometry = feature.getGeometry();
      if (geometry instanceof LineString) {
        const result = this.measureLineString(geometry);
        this.emit('measureend', {
          type: MeasureType.DISTANCE,
          result,
          feature
        });
      } else if (geometry instanceof Polygon) {
        const result = this.measurePolygon(geometry);
        this.emit('measureend', {
          type: MeasureType.AREA,
          result,
          feature
        });
      }
    });

    this.map.addInteraction(this.drawInteraction);
    this.emit('measurestart', this.measureType);
  }

  /**
   * 停止测量
   */
  stop(): void {
    if (this.map) {
      if (this.drawInteraction) {
        this.map.removeInteraction(this.drawInteraction);
        this.drawInteraction = null;
      }
      if (this.modifyInteraction) {
        this.map.removeInteraction(this.modifyInteraction);
        this.modifyInteraction = null;
      }
    }
    this.currentFeature = null;
    this.emit('measurestop');
  }

  /**
   * 清空测量结果
   */
  clear(): void {
    if (this.source) {
      this.source.clear();
      this.currentFeature = null;
      this.emit('clear');
    }
  }

  /**
   * 获取当前测量结果
   */
  getResult(): MeasureResult | null {
    if (!this.currentFeature) return null;

    const geometry = this.currentFeature.getGeometry();
    if (geometry instanceof LineString) {
      return this.measureLineString(geometry);
    } else if (geometry instanceof Polygon) {
      return this.measurePolygon(geometry);
    }

    return null;
  }

  /**
   * 销毁测量工具
   */
  destroy(): void {
    this.stop();
    
    if (this.map) {
      if (this.snapInteraction) {
        this.map.removeInteraction(this.snapInteraction);
        this.snapInteraction = null;
      }
      if (this.layer) {
        this.map.removeLayer(this.layer);
      }
    }

    this.map = null;
    this.removeAllListeners();
    this.emit('destroy');
  }
}

